/*
Classe administrativa, manipula os dados e repassa para as outras classes (meio que toma conta de tudo),
se localiza no centro da aplicação. Esta classe deve ter um método para carregar todas as outras classes,
e trata as exeções.
 */
package servidor;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Vector;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Servidor extends Thread {

    private static Vector SAIDA_CLIENTES_LOGADOS = new Vector();
    private static List LISTA_LOGIN_DE_CLIENTES = new ArrayList();
    private static List LISTA_SENHA_DE_CLIENTES = new ArrayList();
    private static List LISTA_DE_CLIENTES_LOGADOS = new ArrayList();
    private String login;
    private String senha;
    private Conexao conexao;
    private Socket conexaoCliente;
    private static boolean primeiraVez = true;
    BufferedReader entrada;
    PrintStream saida;
    Interface servidor;

    public Servidor() {
        servidor = new Interface();
        conexao = new Conexao();
        if (primeiraVez) {
            LISTA_LOGIN_DE_CLIENTES.add("felipe");
            LISTA_LOGIN_DE_CLIENTES.add("rafael");
            LISTA_SENHA_DE_CLIENTES.add("fel");
            LISTA_SENHA_DE_CLIENTES.add("raf");
            primeiraVez = false;
            IniciaServidor();
        } else {

            escutaNovoCliente();
            try {
                prepararPassagemDeDados();
            } catch (IOException e) {
                servidor.mostraErro("IOException: " + e);
            }
        }

    }

    private void prepararPassagemDeDados() throws IOException {
        entrada = new BufferedReader(new InputStreamReader(conexaoCliente.getInputStream()));
        saida = new PrintStream(conexaoCliente.getOutputStream());
    }

    private void IniciaServidor() {
        try {
            conexao.criaSocketServidor();

            servidor.mostraNaTela("ServidorSocket rodando na porta 7001\n");

        } catch (IOException e) {
            servidor.mostraErro("IOException: " + e);
        }
    }

    private void escutaNovoCliente() {
        try {
            setConexaoCliente(conexao.retornaConexaoNovaCliente());

        } catch (IOException e) {
            servidor.mostraErro("IOException: " + e);
        }

    }

    private void setConexaoCliente(Socket conexaoCliente) {
        this.conexaoCliente = conexaoCliente;
    }

    private boolean verificaLoginExistente() {
        return LISTA_LOGIN_DE_CLIENTES.contains(login);
    }

    private boolean vericaSenhaUsuario() {
        int numeroUsuario = LISTA_LOGIN_DE_CLIENTES.indexOf(login);
        return LISTA_SENHA_DE_CLIENTES.get(numeroUsuario).equals(senha);
    }

    private boolean verificaUsuarioLogado() {
        return LISTA_DE_CLIENTES_LOGADOS.contains(login);
    }

    private void adicionaUsuario() {
        LISTA_DE_CLIENTES_LOGADOS.add(login);
        SAIDA_CLIENTES_LOGADOS.add(saida);
    }

    private void removeNomeListaUsuariosLogados(String login) {
        LISTA_DE_CLIENTES_LOGADOS.remove(login);
    }

    @Override
    public void run() {

        try {
            this.login = entrada.readLine();
            this.senha = entrada.readLine();

            if (verificaLoginExistente()) {
                if (vericaSenhaUsuario()) {
                    if (verificaUsuarioLogado()) {
                        saida.println("Este usuário ja está logado");
                        conexaoCliente.close();
                        return;
                    } else {
                        adicionaUsuario();
                        sendToAll(saida," entrou ", "no chat.");
                    }

                    String mensagem = entrada.readLine();

                    while (mensagem != null && !(mensagem.trim().equals(""))) {
                        sendToAll(saida, " escreveu: ", mensagem);
                        mensagem = entrada.readLine();
                    }

                    servidor.mostraNaTela(this.login + " saiu do bate-papo!");
                    sendToAll(saida, " saiu", " do bate-papo!");
                    removeNomeListaUsuariosLogados(this.login);
                    SAIDA_CLIENTES_LOGADOS.remove(saida);
                    conexaoCliente.close();


                } else {
                    saida.println("Senha errada.");
                    conexaoCliente.close();
                    return;
                }
            } else {
                saida.println("Login Inexistente.");
                conexaoCliente.close();
                return;
            }

        } catch (IOException ex) {
            Logger.getLogger(Servidor.class.getName()).log(Level.SEVERE, null, ex);
        }

    }

    public void sendToAll(PrintStream saida, String acao, String mensagem) throws IOException {
        Enumeration e = SAIDA_CLIENTES_LOGADOS.elements();
        while (e.hasMoreElements()) {
            PrintStream chat = (PrintStream) e.nextElement();
            if (chat != saida) {
                chat.println(this.login + acao + mensagem);
            }
        }
    }
}
